package com.scalar.chiptrack.adaptor.utils;

import java.util.LinkedList;
import java.util.Date;
import java.util.TimeZone;
import java.util.List;
import java.util.ArrayList;
import java.text.SimpleDateFormat;
import java.text.ParseException;

import com.scalar.chiptrack.utils.StringUtils;
import org.apache.poi.ss.usermodel.Cell;


/**
 * User: sujan
 * Date: Dec 5, 2008
 * Time: 3:59:46 PM
 */
public class ParserResultXLSImpl implements ParserResult
{
    private Object[][] data;
    private LinkedList headings;
    private boolean headingsCaseSensitive = false;
    private int currRowIdx = -1;

    public boolean next()
    {
        if ( data != null && ((currRowIdx +1) < data.length ) )
        {
            currRowIdx = currRowIdx +1;
        }
        else
        {
            return false;
        }
        return true;
    }
    public void reset()
    {
        currRowIdx = -1;
    }
    public Object[][] getData() {
        return data;
    }

    public void setData(Object[][] data) {
        this.data = data;
    }

    public LinkedList getHeadings() {
        return headings;
    }

    public void setHeadings(LinkedList headings) {
        this.headings = headings;
    }
    public String getString ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getString ( colIdx );
    }
    public String getString( int colIdx )
    {
        checkCurrentState();
        String value = null;

        if ( data[currRowIdx].length > colIdx )
        {
            Cell cell = (Cell)data[currRowIdx][colIdx];

            if ( cell != null )
            {                   
                if ( cell.getCellType() == Cell.CELL_TYPE_STRING )
                {
                    value = cell.getStringCellValue();
                }
                else if ( cell.getCellType() == Cell.CELL_TYPE_BLANK )
                {
                    value = null;
                }
                else if ( cell.getCellType() == Cell.CELL_TYPE_ERROR )
                {
                    value = null;
                }
                else if ( cell.getCellType() == Cell.CELL_TYPE_NUMERIC )
                {
                    value = (int)cell.getNumericCellValue() +"";
                }
                else if ( cell.getCellType() == Cell.CELL_TYPE_FORMULA )
                {
                    if ( cell.getCachedFormulaResultType() == Cell.CELL_TYPE_STRING )
                    {
                          value =  cell.getStringCellValue() ;
                    }
                    else
                    {
                        value = (int)cell.getNumericCellValue() +"";
                    }
                }
                else
                {
                    value = cell.getStringCellValue().trim();
                }
            }
        }

        return value;
    }
    public int getInt ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getInt ( colIdx );
    }
    public int getInt ( int colIdx )
    {
        checkCurrentState();
        int value = 0;
        if ( data[currRowIdx].length > colIdx )
        {
            Cell cell = (Cell)data[currRowIdx][colIdx];

            if ( cell != null )
            {                   
                if ( cell.getCellType() == Cell.CELL_TYPE_NUMERIC )
                {
                    value = (int)cell.getNumericCellValue();
                }
                else if ( cell.getCellType() == Cell.CELL_TYPE_BLANK )
                {
                    //value = "";
                }
                else if ( cell.getCellType() == Cell.CELL_TYPE_ERROR )
                {
                    //;
                }
                else if ( cell.getCellType() == Cell.CELL_TYPE_FORMULA )
                {
                    if ( cell.getCachedFormulaResultType() == Cell.CELL_TYPE_STRING )
                    {
                          value =  Integer.parseInt(cell.getStringCellValue() ) ;
                    }
                    else
                    {
                        value = (int)cell.getNumericCellValue();
                    }
                }
                else
                {
                    if ( cell.getStringCellValue() != null && cell.getStringCellValue().trim().length() > 0 )
                    {
                        String contents = cell.getStringCellValue().trim().replaceAll(",", "");

                        if ( contents.indexOf(".")!= -1 )
                        {
                            contents = contents.substring(0, contents.indexOf("."));
                        }   
                        
                        value = Integer.parseInt( contents );
                    }
                }
            }
        }    
        return value;
    }
    public double getDouble ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }

        return getDouble ( colIdx );
    }
    public double getDouble ( int colIdx )
    {
        checkCurrentState();
        double value = 0;
        if ( data[currRowIdx].length > colIdx )
        {
            Cell cell = (Cell)data[currRowIdx][colIdx];

            if ( cell != null )
            {
                if ( cell.getCellType() == Cell.CELL_TYPE_NUMERIC )
                {
                    value = cell.getNumericCellValue();
                }
                else if ( cell.getCellType() == Cell.CELL_TYPE_FORMULA )
                {
                    value = cell.getNumericCellValue();
                }
                else
                {
                    value = Double.parseDouble( cell.getStringCellValue().trim() );
                }
            }
        }
        return value;
    }
    public Date getDate ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getDate ( colIdx );
    }
    public Date getDate ( int colIdx )
    {
        checkCurrentState();
        Date value = null;
        if ( data[currRowIdx].length > colIdx )
        {
            Cell cell = (Cell)data[currRowIdx][colIdx];

            if ( cell != null )
            {
                if ( cell.getCellType() == Cell.CELL_TYPE_NUMERIC )
                {
                    Date dt = cell.getDateCellValue(); //returns the date after converting the given date(considered to be GMT) into current system TimeZone.

                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    sdf.setTimeZone( TimeZone.getTimeZone("GMT") );
                    value = StringUtils.format(sdf.format(dt), "yyyy-MM-dd HH:mm:ss");//converting back to GMT i.e original given date values

                    return value;//given date in the excel file
                }
            }
        }
        return value;
    }

    public Date getDate(int colIdx, String inputFormat)
    {
        checkCurrentState();
        String strValue = getString ( colIdx );
        Date value = null;
        if ( strValue != null )
        {
            SimpleDateFormat sdf = new SimpleDateFormat(inputFormat);
            try
            {
                value = sdf.parse(strValue);
            }
            catch ( ParseException e ) { }
        }
        return value;
    }

    public Date getDate(String colName, String inputFormat) 
    {
        checkCurrentState();
        int colIdx = headings.indexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getDate ( colIdx, inputFormat );
    }

    public String getContents ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getContents ( colIdx );
    }
    public String getContents( int colIdx )
    {
        checkCurrentState();
        Cell cell = (Cell)data[currRowIdx][colIdx];
        String value = null;
        if ( cell != null )
        {
            value = cell.getStringCellValue();
        }
        return value;
    }

    public Object getObject(String colName)
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getObject ( colIdx );
    }


    public Object getObject(int colIdx)
    {
        checkCurrentState();

        return data[currRowIdx][colIdx];
    }

    public void checkCurrentState()
    {
        if ( currRowIdx == -1 )
            throw new RuntimeException ( "Result Cursor is at start location, Please use next() to move to the first record" );
        if ( currRowIdx >= data.length )
            throw new RuntimeException ( "Result Cursor is at End location, use reset() to start from the initial" );
    }

    public int getRowCount()
    {
        return data==null ? 0 : data.length;
    }

    public int getFileRowIdx()
    {
        checkCurrentState();
        Object[] cells = data[currRowIdx];
        Cell cell = null;
        if ( cells != null )
        {
            for ( int i=0; i < cells.length; i++ )
            {
                cell = (Cell)cells[i];
                if ( cell != null)
                {
                    break;
                }
            }
        }
        if ( cell != null )
        {
            return cell.getRowIndex();
        }
        return currRowIdx;
    }

    public List checkRequiredFieldsAvailable(List requiredHeadings)
    {
        List headingsNotPresent = new ArrayList();
        if ( requiredHeadings != null && headings != null )
        {
            for ( int i=0; i < requiredHeadings.size(); i++ )
            {
                if ( headingsCaseSensitive )
                {
                    if ( !headings.contains( requiredHeadings.get(i) ) )
                    {
                        headingsNotPresent.add ( requiredHeadings.get(i) );
                    }
                }
                else
                {
                    String required = requiredHeadings.get(i).toString();
                    boolean contains = false;
                    for ( int j=0; j < headings.size(); j++ )
                    {
                        String heading = headings.get(j).toString();
                        if ( required == null )
                        {
                            if ( heading == null )
                            {
                                contains = true;
                                break;
                            }
                        }
                        else if ( required.equalsIgnoreCase( heading ) )
                        {
                            contains = true;
                            break;
                        }
                    }
                    if ( !contains )
                    {
                        headingsNotPresent.add ( requiredHeadings.get(i) );
                    }
                }
            }
        }
        return headingsNotPresent.isEmpty() ? null :headingsNotPresent;
    }
    public int getIndexOf(String headingName)
    {
        headingName = headingName.trim();
        int idx = -1;
        if ( headings != null )
        {
            if ( headingsCaseSensitive )
            {
                idx = headings.indexOf(headingName);
            }
            else
            {
                for ( int i=0; i< headings.size(); i++ )
                {                       
                    String value = headings.get(i) != null ? headings.get(i).toString() : null;

                    if ( headingName == null )
                    {
                        if ( value == null )
                        {
                            idx = i;
                            break;
                        }
                    }
                    else
                    {
                        if ( value != null )
                        {
                            if ( headingName.equalsIgnoreCase( value.trim() ) )
                            {
                                idx = i;
                                break;
                            }
                        }
                    }
                }
            }
        }
        return idx;
    }


    public void moveTo(int rowIdx)
    {
        int cuurentRowIdx = currRowIdx;
        currRowIdx = rowIdx;
        try
        {
            checkCurrentState();
        }
        catch( RuntimeException re )
        {
            currRowIdx = cuurentRowIdx;
            throw re;
        }
    }

    public int getColumnCount()
    {
        return (data==null || data[0] == null ) ? 0 : data[0].length;
    }

    public boolean isHeadingsCaseSensitive() {
        return headingsCaseSensitive;
    }

    public void setHeadingsCaseSensitive(boolean headingsCaseSensitive) {
        this.headingsCaseSensitive = headingsCaseSensitive;
    }
}
